#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Author:Lijiacai
Email:1050518702@qq.com
===========================================
CopyRight@JackLee.com
===========================================
"""
import hashlib
import time
import base64
import os
import re
import sys
import json
import pandas
import chardet
import graphene
import config
from common.view import BaseApi
from resource.lijiacai.utils import tool


# class SearchList(BaseApi, tool.Business):
#     name = "SearchList"
#     description = "列表搜索页"
#
#     class Argument:
#         KEYWORD = graphene.String(description="查询关键字")
#
#         STARTTIME = graphene.String(description="事件起始时间")
#         ENDTIME = graphene.String(description="事件结束时间")
#
#         DATA_SOURCE = graphene.String(description="数据来源【用车后台|七鱼客服|调度后台|线下数据】", default='')
#         DATA_TYPE = graphene.String(description="数据类型【车辆|用户|账户|站点】", required=True, default='')
#
#         page_size = graphene.Int(description="单页容量", default=10)
#         page_num = graphene.Int(description="页数", default=1)
#
#     class Return:
#         class OrderSearchList1(graphene.ObjectType):
#             class OrderSearchList2(graphene.ObjectType):
#                 HEAD = graphene.String(description="标题")
#                 NO = graphene.String(description="单据编号")
#                 CONTENT = graphene.String(description="描述内容文本")
#                 ACTION_TIME = graphene.String(description="时间")
#                 DATA_TYPE = graphene.String(description="数据类型【车辆|用户|账户|站点】")
#
#             _id = graphene.String(description="记录id")
#             _score = graphene.Float(description="查询分数")
#             _source = graphene.Field(OrderSearchList2, description="")
#
#         class OrderSearchList3(graphene.ObjectType):
#             HEAD = graphene.String(description="标题")
#             NO = graphene.String(description="单据编号")
#             CONTENT = graphene.String(description="描述内容文本")
#             ACTION_TIME = graphene.String(description="时间")
#             DATA_TYPE = graphene.String(description="数据类型【车辆|用户|账户|站点】")
#
#         rows = graphene.List(OrderSearchList1, description="结果列表")
#         total = graphene.Int(description="总数")
#         stat = graphene.Int(description="相关去重统计总数")
#
#     def validate_privilege(self, token_info, **kwargs):
#         pass
#
#     def deal(self, token_info, prilivege_info, **kwargs):
#         dsl_args = self.dsl_args(self.arguments)  # 解析查询
#         # todo:添加精确过滤查询条件，添加聚合参数
#         dsl_args["filter_condition"] = {"DATA_SOURCE": self.arguments.get("condition", {}).get("DATA_SOURCE"),
#                                         "DATA_TYPE": self.arguments.get("condition", {}).get("DATA_TYPE")}
#         dsl_args["aggs_condition"] = ["HEAD"]
#         ###
#         dsl = self.dsl(**dsl_args)
#         data = self.client.search(index=config.es_index, body=json.dumps(dsl))
#         total = data.get("hits", {}).get("total")
#         rows = data.get("hits", {}).get("hits", [])
#         stat = data.get("hits", {}).get("aggregations", {}).get("distinct_HEADS", {}).get("value", 0)
#         result = []
#         for one in rows:
#             CONTENT = json.loads(one.get("_source", {}).get("DATA", "{}")).get("CONTENT")
#             one["CONTENT"] = CONTENT
#             result.append(one)
#         return {"total": total, "rows": result, "stat": stat}


class SearchList(BaseApi, tool.Business):
    name = "SearchList"
    description = "搜搜SearchList"

    class Argument:
        HEAD = graphene.String(description="指定HEAD查询,用户不可自己输入")
        NO = graphene.String(description="指定NO查询,用户不可自己输入")
        KEYWORD = graphene.String(description="查询关键字")

        STARTTIME = graphene.String(description="事件起始时间")
        ENDTIME = graphene.String(description="事件结束时间")

        DATA_SOURCE = graphene.String(description="数据来源【用车后台|七鱼客服|调度后台|线下数据】")
        DATA_TYPE = graphene.String(description="数据类型【车辆|用户|账户|站点】")
        NO_TYPE = graphene.String(description="单据类型【订单|调度工单|客服工单|系统日志|线下数据】")

        page_size = graphene.Int(description="单页容量", default=10)
        page_num = graphene.Int(description="页数", default=1)

    class Return:
        class SearchList1(graphene.ObjectType):
            class SearchList2(graphene.ObjectType):
                HEAD = graphene.String(description="标题")
                NO = graphene.String(description="单据编号")
                CONTENT = graphene.String(description="描述内容文本")
                ACTION_TIME = graphene.String(description="时间")
                DATA_SOURCE = graphene.String(description="数据来源【用车后台|七鱼客服|调度后台|线下数据】")
                DATA_TYPE = graphene.String(description="数据类型【车辆|用户|账户|站点】")
                NO_TYPE = graphene.String(description="单据类型【订单|调度工单|客服工单|系统日志|线下数据】")
                ACTION_NAME = graphene.String(description="操作人")

            _id = graphene.String(description="记录id")
            _score = graphene.Float(description="查询分数")
            _source = graphene.Field(SearchList2, description="")

        class SearchList3(graphene.ObjectType):
            HEAD = graphene.String(description="标题")
            NO = graphene.String(description="单据编号")
            CONTENT = graphene.String(description="描述内容文本")

            ACTION_TIME = graphene.String(description="时间")
            DATA_TYPE = graphene.String(description="数据类型【车辆|用户|账户|站点】")

        rows = graphene.List(SearchList1, description="结果列表")
        total = graphene.Int(description="总数")
        stat = graphene.Int(description="数据类型去重统计总数")
        base_info = graphene.String(description="基础信息")

    def validate_token(self, info, **kwargs):
        # token = info.context.get("token")
        # print(token)
        pass

    def deal(self, token_info, prilivege_info, **kwargs):
        dsl_args = self.dsl_args(self.arguments)  # 解析查询
        # todo:添加精确过滤查询条件，添加聚合参数
        dsl_args["filter_condition"] = {"DATA_SOURCE": self.arguments.get("condition", {}).get("DATA_SOURCE"),
                                        "DATA_TYPE": self.arguments.get("condition", {}).get("DATA_TYPE"),
                                        "NO_TYPE": self.arguments.get("condition", {}).get("NO_TYPE"),
                                        "NO": self.arguments.get("condition", {}).get("NO"),
                                        "HEAD": self.arguments.get("condition", {}).get("HEAD")}
        if self.arguments.get("condition", {}).get("HEAD"):
            dsl_args["aggs_condition"] = ["NO"]
        else:
            dsl_args["aggs_condition"] = ["HEAD"]
        ###
        dsl = self.dsl(**dsl_args)
        data = self.client.search(index=config.es_index, body=json.dumps(dsl))
        total = data.get("hits", {}).get("total")
        rows = data.get("hits", {}).get("hits", [])
        if self.arguments.get("condition", {}).get("HEAD"):
            stat = data.get("aggregations", {}).get("distinct_NOS", {}).get("value", 0)
        else:
            stat = data.get("aggregations", {}).get("distinct_HEADS", {}).get("value", 0)
        result = []
        base_info = ""
        for one in rows:
            if not base_info and (
                    self.arguments.get("condition", {}).get("HEAD") or self.arguments.get("condition", {}).get("NO")):
                base_info = one.get("_source", {}).get("DATA", "{}")
                if self.arguments.get("condition", {}).get("DATA_TYPE") == "车辆":
                    base_info = json.loads(base_info)
                    dsl_args = {}
                    dsl_args["filter_condition"] = {
                        "HEAD": self.arguments.get("condition", {}).get("HEAD"),
                        "NO": self.arguments.get("condition", {}).get("NO")}
                    dsl = self.dsl(**dsl_args)
                    dsl["min_score"] = 0
                    data = self.client.search(index=config.vehicle_base_info_index, body=json.dumps(dsl))
                    hits = data.get("hits", {}).get("hits", [])
                    if hits:
                        base_info_ = json.loads(hits[0].get("_source", {}).get("DATA", "{}"))
                        base_info.update(base_info_)
                    base_info = str(json.dumps(base_info, ensure_ascii=False))
            CONTENT = json.loads(one.get("_source", {}).get("DATA", "{}")).get("CONTENT")
            one["_source"]["CONTENT"] = CONTENT
            result.append(one)
        return {"total": total, "rows": result, "stat": stat, "base_info": base_info}


class SimpleLogin(BaseApi, tool.Business):
    name = "SimpleLogin"
    description = "简单登录"

    class Argument:
        UserName = graphene.String(description="账户名称", required=True)
        Password = graphene.String(description="账户密码", required=True)

    class Return:
        token = graphene.String(description="验证token")

    def validate_privilege(self, token_info, **kwargs):
        pass

    def deal(self, token_info, prilivege_info, **kwargs):
        UserName = self.arguments.get("condition", {}).get("UserName")
        Password = self.arguments.get("condition", {}).get("Password")
        for k, v in config.user_password.items():
            if (UserName == k and Password == v):
                data = {"UserName": UserName,
                        "Password": Password,
                        "Company": "PAND"}
                res = self.get_base64(json.dumps(data).encode("utf8")).decode("utf8")
                return {"token": res}
        raise Exception("登录失败")


class OffLineFileExportRestful(BaseApi, tool.Business):
    name = "OffLineFileExportRestful"
    description = "线下数据导入"

    class Argument:
        DATATYPE = graphene.String(description="数据类型【线下运营数据|七鱼工单数据】")
        FILEDATA = graphene.String(description="文件base64")
        FILETYPE = graphene.String(description="文件类型【xls|csv|xlsx】")

    class Return:
        succ = graphene.Boolean(description="导入成功")

    def validate_privilege(self, token_info, **kwargs):
        pass

    def deal(self, token_info, prilivege_info, **kwargs):
        DATATYPE = self.arguments.get("condition", {}).get("DATATYPE")
        FILETYPE = self.arguments.get("condition", {}).get("FILETYPE")
        FILEDATA = self.arguments.get("condition", {}).get("FILEDATA")
        filename = f"{time.time()}.{FILETYPE}"
        datas = FILEDATA.split("base64,")
        data_str = base64.b64decode(datas[1])
        fileencoding = chardet.detect(data_str)['encoding']
        with open(filename, "wb") as f:
            f.write(data_str)
        if FILETYPE == "csv":
            data = pandas.read_csv(filename, encoding=fileencoding)
        elif FILETYPE == "xls" or FILETYPE == "xlsx":
            data = pandas.read_excel(filename, encoding=fileencoding)
        else:
            raise Exception("文件类型错误")
        flow_name = []
        for i in list(data.columns):
            if "流转节点" in i:
                flow_name.append(i)
        os.remove(filename)
        if DATATYPE == "线下运营数据":
            cols = ["日期", "值班",
                    "任务类别", "工单", "车牌号", "车型", "用户姓名", "用户电话",
                    "外勤区域", "外勤人员",
                    # "处理进度", "后续用车状态",
                    "救援详情", "收费金额", "救援结果"]
            data = data[cols]
            # data = data.dropna()
            data["用户电话"] = data["用户电话"].apply(int)
            out = []
            for index, row in data.iterrows():
                result = {}
                for k in cols:
                    result[k] = str(row[k]).strip()
                res = dict(result)
                res["CUSTOMER_HEAD"] = res["用户姓名"] + res["用户电话"]
                res["ACTION_TIME"] = res["日期"]
                time.strptime(res["日期"], "%Y-%m-%d %H:%M:%S")
                res["CONTENT"] = res["救援详情"] + res["救援结果"]
                out.append(res)
            self.update_license_offline_worksheet(out)
            self.update_user_offine_worksheet(out)
            return {"succ": True}
        elif DATATYPE == "七鱼工单数据":
            cols = ["用户姓名", "工单号",
                    "客户联系电话", "车牌号", "订单号", "车辆型号", "创建时间", "工单内容",
                    "状态", "总节点"]
            data["总节点"] = ""
            for col in flow_name:
                data["总节点"] += data[col].map(str)
            data["总节点"] = data["总节点"].apply(self.deal_node)
            data = data[cols]
            data = data.dropna()
            data["客户联系电话"] = data["客户联系电话"].apply(int)
            out = []
            for index, row in data.iterrows():
                result = {}
                for k in cols:
                    result[k] = str(row[k]).strip()
                del result["总节点"]
                for node in row["总节点"]:
                    res = dict(result)
                    res["CUSTOMER_HEAD"] = res["用户姓名"] + res["客户联系电话"]
                    res["ACTION_TIME"] = node.split(";")[1].strip()
                    res["CONTENT"] = node
                    out.append(res)
            self.update_license_qiyu_worksheet(out)
            self.update_user_qiyu_worksheet(out)
            return {"succ": True}
        else:
            raise Exception("线下数据类型错误")

    def deal_node(self, data):
        data = data.replace("nan", "")
        datas = data.split("操作人：")
        result = []
        for i in datas:
            if i.strip():
                result.append(i)
        return result

    def _id_func_order(self, data):
        s = data.get("HEAD") + str(data.get("ACTION_TIME")) + str(data.get("NO")) + data.get("NO_TYPE")
        s = str(s)
        m = hashlib.md5()
        b = s.encode(encoding='utf-8')
        m.update(b)
        str_md5 = m.hexdigest()
        return str_md5

    def update_license_qiyu_worksheet(self, data):
        conf = config.license_qiyu_worksheet
        sql = conf.get("sql")
        sql_fields = conf.get("fields")
        index = conf.get("index")
        es_fields = conf.get("es_fields", {})
        apply_func = None
        _id_func = self._id_func_order

        ####### todo
        # sql = sql.format("2019-11-01", "2020-01-01")
        ######
        O2E = tool.OffLine2Es(data)
        O2E.update(sql=sql, sql_fields=sql_fields, index=index, es_fields=es_fields,
                   _id_func=_id_func)
        O2E.close()

    def update_user_qiyu_worksheet(self, data):
        conf = config.user_qiyu_worksheet
        sql = conf.get("sql")
        sql_fields = conf.get("fields")
        index = conf.get("index")
        es_fields = conf.get("es_fields", {})
        apply_func = None
        _id_func = self._id_func_order

        ####### todo
        # sql = sql.format("2019-11-01", "2020-01-01")
        ######
        O2E = tool.OffLine2Es(data)
        O2E.update(sql=sql, sql_fields=sql_fields, index=index, es_fields=es_fields,
                   _id_func=_id_func)
        O2E.close()

    def update_license_offline_worksheet(self, data):
        conf = config.license_offline_worksheet
        sql = conf.get("sql")
        sql_fields = conf.get("fields")
        index = conf.get("index")
        es_fields = conf.get("es_fields", {})
        apply_func = None
        _id_func = self._id_func_order

        ####### todo
        # sql = sql.format("2019-11-01", "2020-01-01")
        ######
        O2E = tool.OffLine2Es(data)
        O2E.update(sql=sql, sql_fields=sql_fields, index=index, es_fields=es_fields,
                   _id_func=_id_func)
        O2E.close()

    def update_user_offine_worksheet(self, data):
        conf = config.user_offline_worksheet
        sql = conf.get("sql")
        sql_fields = conf.get("fields")
        index = conf.get("index")
        es_fields = conf.get("es_fields", {})
        apply_func = None
        _id_func = self._id_func_order

        ####### todo
        # sql = sql.format("2019-11-01", "2020-01-01")
        ######
        O2E = tool.OffLine2Es(data)
        O2E.update(sql=sql, sql_fields=sql_fields, index=index, es_fields=es_fields,
                   _id_func=_id_func)
        O2E.close()


class OffLineDownLoadModule(BaseApi, tool.Business):
    name = "OffLineDownLoadModule"
    description = "线下数据模板下载"

    class Argument:
        DATATYPE = graphene.String(description="数据类型【线下运营数据|七鱼工单数据】")

    class Return:
        ModuleBase64 = graphene.String(description="模板数据base64")
        FileName = graphene.String(description="文件名称")

    def validate_privilege(self, token_info, **kwargs):
        pass

    def deal(self, token_info, prilivege_info, **kwargs):
        DATATYPE = self.arguments.get("condition", {}).get("DATATYPE")
        if DATATYPE == "线下运营数据":
            with open("./configure/demo2.xlsx", "rb") as f:
                res = self.get_base64(f.read()).decode("utf8")
            # print(res)
        elif DATATYPE == "七鱼工单数据":
            with open("./configure/demo1.xlsx", "rb") as f:
                res = self.get_base64(f.read()).decode("utf8")
            # print(res)

        else:
            raise Exception("数据类型错误")
        return {"ModuleBase64": "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64," + res,
                "FileName": DATATYPE + "模板.xlsx"}
